package net.bat.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;

import javax.activation.MimetypesFileTypeMap;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.bat.dao.UserDAO;
import net.bat.entity.Attach;
import net.bat.util.FileWrapper;
import net.coobird.thumbnailator.Thumbnails;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FileService {

	private static Logger logger = LoggerFactory.getLogger(FileService.class);

	final MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
	@Autowired
	private UserDAO dao;

	@Autowired
	private FileCheck fc;

	@Value("${workpath.win}")
	private String workpath_win;

	@Value("${workpath.linux}")
	private String workpath_linux;

	static private String path_work = null;
	static private String path_upload = null;

	static final String CONTENT_TYPE = "text/html; charset=UTF-8";

	// 由于Rels不会太多 <20，全部重新排序简单可靠
	public void dragDropSort(List<Long> newOrder) {
		List<Attach> objs = dao.queryByWhere(Attach.class, "id in (?1)", new Object[] { newOrder });
		// 检索结果顺序并不与传入的id顺序一致,缓存之，然后按id顺序修改Attach记录
		HashMap<Long, Attach> rm = new HashMap<Long, Attach>();
		for (Attach obj : objs) {
			rm.put(obj.getId(), obj);
		}
		for (int i = 0; i < newOrder.size(); i++) {
			long id = newOrder.get(i);
			Attach obj = rm.get(id);
			obj.setOrd(i);
			dao.save(obj);
		}
		rm.clear();
	}

	@PostConstruct
	public String getPathWork() {
		if (path_work == null) {
			if (File.separatorChar == '/') {
				path_work = workpath_linux;
			} else {
				path_work = workpath_win;
			}
			File dir = new File(path_work);
			if (!dir.exists() || !dir.isDirectory()) {
				dir.mkdirs();
			}
		}
		return path_work;
	}

	public String getPathUpload() {
		if (path_upload == null) {
			path_upload = getPathWork() + File.separator + "upload" + File.separator;
			File dir = new File(path_upload);
			if (!dir.exists() || !dir.isDirectory()) {
				boolean bsucc = dir.mkdirs();
				if (!bsucc) {
					logger.error("create dir fail:" + dir);
				}
			}
		}
		return path_upload;
	}

	public void onOpenFile(String fp, HttpServletRequest request, HttpServletResponse response) throws IOException {
		// 直接通过/fopen/1.jpg 会丢失后缀
		char chsf = '.';
		if (fp.indexOf(chsf) == -1) {
			Attach at = dao.find(Attach.class, Long.parseLong(fp));
			if (at != null) {
				String sf = at.getSuffix();
				if (sf.indexOf(chsf) == -1) {
					fp = fp + chsf + sf;
				} else {
					fp = fp + sf;
				}
			}
		}
		fp = fp.replace("/", File.separator);
		File fileIn = new File(getPathUpload() + fp);

		if (!fileIn.exists()) {
			response.sendRedirect("resources/images/no_image_available.jpg");
			return;
		}
		String s = request.getParameter("size");
		if (s != null) {
			int ds = Integer.parseInt(s);
			fileIn = getFnBySize(fileIn, ds);
		}
		String ftype = "";
		int ind = fp.lastIndexOf('.');
		if (ind != -1) {
			ftype = fp.substring(ind).toLowerCase();
		}
		response.setContentType(fileTypeMap.getContentType(fileIn));
		response.addHeader("Content-Disposition", "attachment;filename=" + fp);
		InputStream is = new FileInputStream(fileIn);
		OutputStream os = response.getOutputStream();// 得到输出流
		byte data[] = new byte[4096];// 缓冲字节数
		int size = is.read(data);
		while (size != -1) {
			os.write(data, 0, size);
			size = is.read(data);
		}
		is.close();
		os.flush();
		os.close();
	}

	/**
	 * 抽点
	 * 
	 * @param fileIn
	 * @param ds
	 * @return
	 * @throws IOException
	 */
	static public File getFnBySize(File fileIn, int ds) throws IOException {
		if ((fileIn == null) || !fileIn.exists()) {
			return null;
		}
		String fp = fileIn.getPath();
		int pos = fp.lastIndexOf(".");
		String suffix = fp.substring(pos + 1).toLowerCase();
		String fp1 = fp.substring(0, pos) + "_" + ds + "." + suffix;
		File fileIn1 = new File(fp1);
		// 抽点文件不存在，抽之
		if (!fileIn1.exists() && (suffix.equals("jpg") || suffix.equals("png"))) {
			Thumbnails.of(fileIn).size(ds, ds).outputFormat(suffix).toFile(fileIn1);
		}
		return fileIn1;
	}

	private void clearAttach(Attach ca) {
		FileWrapper.clearFiles(getPathUpload() + ca.getPath());
	}

	public void onFileUpload(MultipartFile[] files, HttpServletRequest request, HttpServletResponse response)
			throws IllegalStateException, IOException {
		String entity_to = request.getParameter("entity_to");
		String entity_rel = request.getParameter("entity_rel");
		String entity_id = request.getParameter("entity_id");
		response.setContentType(CONTENT_TYPE);
		// 检查form是否有enctype="multipart/form-data"
		StringBuffer sbuf = null;
		// c4w 7.16 上传不一定关联，此方法是复用的，需要判断是否需要关联
		for (MultipartFile file : files) {
			if (file.isEmpty()) {
				continue;
			}
			String errinf = fc.valid(entity_rel, file);
			if (errinf != null) {
				throw new IOException(errinf);
			}
			String ofn = file.getOriginalFilename();
			// 写入的文件名
			Attach fe;
			if (entity_id == null) {
				fe = new Attach();
			} else {
				fe = dao.find(Attach.class, Long.parseLong(entity_id));
				clearAttach(fe);
			}
			fe.setFname(ofn);
			fe.setTitle(ofn);
			fe.setFsize((int) file.getSize());
			fe.setSuffix(FileWrapper.getFileExt(ofn));
			// 上传并关联
			if (entity_rel != null) {
				fe.setEid(Integer.parseInt(request.getParameter("entity_rel_to")));
				fe.setEname(entity_rel);
			}
			dao.savel(fe, null);
			// 利用attach id重命名文件
			String fnp = fe.getId() + "." + fe.getSuffix();
			fe.setPath(fnp);
			dao.update(fe);

			String path = getPathUpload() + fnp;
			// 写入文件到既定目录
			if (sbuf == null) {
				sbuf = new StringBuffer(fnp);
			} else {
				sbuf.append(";" + fnp);
			}
			File localFile = new File(path);
			file.transferTo(localFile);
		}
		PrintWriter out = response.getWriter();
		out.println("[OK]" + sbuf.toString());
	}

}